import re
from functools import wraps
import Levenshtein


def hump2under_line(text):
    lst = []
    for index, char in enumerate(text):
        if char.isupper() and index != 0:
            lst.append("_")
        lst.append(char)
    return "".join(lst).lower()


def _common_process(func):
    @wraps(func)
    def wrapper(*args):
        candidate_text = args[-1]
        others = list(args[0:-1])
        candidate_text = re.sub("[：;；]", ":", candidate_text)
        candidate_lst = candidate_text.split(":")
        if len(candidate_lst) <= 1:
            candidate_text = candidate_text
        else:
            candidate_text = "".join(candidate_lst[1:])
        others.append(candidate_text)
        candidate_text = func(*others)
        candidate_text = re.sub("[\\\\。\\-,\"，$#+&*']", "", candidate_text)
        return candidate_text
    return wrapper


class ExactCandidateFields(object):
    def __init__(self, regular_map):
        self._regular_map = regular_map

    @staticmethod
    def businessScope(candidate_text):
        pattern = "^(.{0,10}范围|经营范.{0,2})(.*)"
        _search = re.search(pattern, candidate_text)
        if not _search:
            return candidate_text
        return _search.groups()[-1]

    @_common_process
    def productSpecification(self, candidate_text):
        return re.split("规格|型号", candidate_text)[-1]

    @_common_process
    def supplierName(self, candidate_text):
        _match = re.search("^(企业|公司|字号|单位|经营者)?名?称?(.*)", candidate_text)
        if not _match:
            return candidate_text
        return _match.groups()[-1]

    @_common_process
    def legalRepresentative(self, candidate_text):
        _match = re.search("^(法定代[表吃]人|负责人|经营者|法定代表)?姓?名?(.*)", candidate_text)
        if not _match:
            return candidate_text
        return _match.groups()[-1]

    @_common_process
    def common_exact(self, field_key, candidate_text):
        _search = re.search(self._regular_map[field_key], candidate_text)
        if not _search:
            return candidate_text
        return _search.groups()[-1]


class LevenshteinRatio(object):
    def __init__(self, predict_label, truth_label, similarity=True):
        self._predict_label = predict_label
        self._truth_label = truth_label
        self._similarity = similarity
        self.result = self.calculate()

    def calculate(self):
        result = dict()
        ignore_keys = ["certificateType", "subCertificateName", "originalData"]
        similarities = []
        for key, val in self._predict_label.items():
            each = dict()
            if key in ignore_keys:
                result[key] = val
                continue
            truth = self._truth_label.get(key, "")
            truth = "" if truth is None else truth
            sim = round(Levenshtein.ratio(val, truth), 3)
            each["predictData"] = val
            each["srcData"] = truth
            each["similarity"] = sim
            similarities.append(sim)
            result[key] = each
        result["totalSimilarity"] = round(sum(similarities) / len(similarities), 3)
        return result
